package elephant.rpc.client.core;

import java.lang.reflect.Method;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import elephant.rpc.client.RPCClient;
import elephant.rpc.server.core.BizException;
import elephant.rpc.server.message.RPCMessage;
import elephant.rpc.server.message.RPCRequest;
import elephant.rpc.server.session.RPCSession;

/**
 * 
 * @author skydu
 *
 */
public class RPCSyncInvocationHandler extends RPCInvocationHandler {
	//
	private static Logger logger=LoggerFactory.getLogger(RPCSyncInvocationHandler.class);
	//
	public RPCSyncInvocationHandler(
			RPCClient client,
			List<RPCSession> sessions) {
		super(client,sessions);
	}
	//
	@Override
	protected Object invoke0(RPCRequest req,Method method) throws Throwable {
		req.getMessage().isAsync=false;
		long requestId=req.getMessage().id;
		ResponseLock lock=new ResponseLock();
		client.getSyncLockMap().put(requestId,lock);
		req.getSession().write(req.getMessage());
		synchronized (lock){
			try {
				int rpcTimeout=client.getRpcTimeout();
				while(lock.responseMessage==null){
					lock.wait(rpcTimeout);
					long endTime=System.currentTimeMillis();
					if(endTime-req.getStartTime()>rpcTimeout
							&&lock.responseMessage==null){
						client.getSyncLockMap().remove(requestId);
						throw new RuntimeException("Request:"+req.getMessage().id
								+" timeout."+req.getStartTime()+"->"
								+endTime+"/"+(endTime-req.getStartTime()));
					
					}
				}
			}catch (InterruptedException e) {
				client.getSyncLockMap().remove(requestId);
				logger.error(e.getMessage(),e);
				throw new Exception(e.getMessage(),e);
			}
			//收到回包
			RPCMessage rsp=(RPCMessage) lock.responseMessage;
			if (RPCMessage.getOtherException(rsp)!=null) {
				throw RPCMessage.getOtherException(rsp);
			}
			if(RPCMessage.getBizExceptionCode(rsp)!=0){
				BizException be=new BizException(
						RPCMessage.getBizExceptionCode(rsp),
						RPCMessage.getBizExceptionMessage(rsp));
				throw be;
			}
			client.getSyncLockMap().remove(requestId);
			return RPCMessage.getRetValue(rsp);
		}
	}
}
